---
title: Astro 语法
description: .astro 组件语法简介。
i18nReady: true
---

**如果你了解 HTML，那么你已经有能力编写第一个 Astro 组件了。**

Astro 组件语法是 HTML 的超集。这个语法[旨在让任何有编写 HTML 或 JSX 经验的人都感到熟悉](#astro-和-jsx-间的差异) ，并增加了对组件和 JavaScript 表达式的支持。

## 类 JSX 表达式

你可以在 Astro 组件的两个代码围栏(`---`)之间的 frontmatter 组件脚本内部定义本地 JavaScript 变量。然后，可以使用类似 JSX 的表达式将这些变量注入到组件的 HTML 模板中！

:::note[动态 vs 响应式]

使用这种方法，你可以在 frontmatter 里设置计算的**动态**值。但是一旦设置完，这些值就不是**响应式**的了，也永远不会改变。Astro 组件是在渲染阶段中只运行一次的模板。

请参阅下面的更多例子 [Astro 和 JSX 之间的差异](#astro-和-jsx-间的差异)。
:::

### 变量

可以使用花括号语法将局部变量添加到 HTML 中:

```astro title="src/components/Variables.astro" "{name}"
---
const name = "Astro";
---
<div>
  <h1>你好 {name}!</h1>  <!-- 输出 <h1>你好 Astro!</h1> -->
</div>
```

### 动态属性

可以在花括号中使用局部变量将属性值传递给 HTML 元素和组件:

```astro title="src/components/DynamicAttributes.astro" "{name}" "${name}"
---
const name = "Astro";
---
<h1 class={name}>支持属性表达式</h1>

<MyComponent templateLiteralNameAttribute={`MyNameIs${name}`} />
```

:::caution
HTML 属性将转换为字符串，因此不能将函数和对象传递给 HTML 元素。
例如，不能为 Astro 组件中的 HTML 元素分配事件处理函数:

```astro title="别这样做.astro"
---
function handleClick () {
    console.log("button clicked!");
}
---
<!-- ❌ 这样行不通 ❌ -->
<button onClick={handleClick}>点击我的时候什么都不会发生！</button>
```

相反，使用客户端脚本来添加事件处理函数，就像在普通的 JavaScript 中那样:

```astro title="像这样做.astro"
---
---
<button id="button">Click Me</button>
<script>
  function handleClick () {
    console.log("button clicked!");
  }
  document.getElementById("button").addEventListener("click", handleClick);
</script>
```
:::

### 动态 HTML

可以在类 JSX 函数中使用局部变量来产生动态生成的 HTML 元素:

```astro title="src/components/DynamicHtml.astro" "{item}"
---
const items = ["Dog", "Cat", "Platypus"];
---
<ul>
  {items.map((item) => (
    <li>{item}</li>
  ))}
</ul>
```

Astro 可以使用 JSX 逻辑运算符和三元表达式有条件地显示 HTML。

```astro title="src/components/ConditionalHtml.astro" "visible"
---
const visible = true;
---
{visible && <p>Show me!</p>}

{visible ? <p>Show me!</p> : <p>Else show me!</p>}
```

### 动态标签

你还可以通过将变量设置为 HTML 标签或组件导入来使用动态标签:

```astro title="src/components/DynamicTags.astro" /Element|(?<!My)Component/
---
import MyComponent from "./MyComponent.astro";
const Element = 'div'
const Component = MyComponent;
---
<Element>Hello!</Element> <!-- 渲染成 <div>Hello!</div> -->
<Component /> <!-- 渲染成 <MyComponent /> -->
```

当使用动态标签时：

- **变量名首字母必须大写**。例如，使用 `Element`，而不是 `element`。否则，Astro 将尝试把变量名渲染为文本 HTML 标签。

- **不支持 hydration 指令**。当使用[`client:*` hydration 指令时](/zh-cn/guides/framework-components/#激活组件)，Astro 需要知道哪些组件要捆绑到生产环境中，而动态标签模式阻止了这一点。

### 片段

Astro 支持使用 `<Fragment> </Fragment>` 或简写成 `<> </>` 包装多个元素。

当添加[`set:*` 指令](/zh-cn/reference/directives-reference/#sethtml)时，片段对于避免包装元素也很有用，如下面的示例所示:

```astro title="src/components/SetHtml.astro" "Fragment"
---
const htmlString = '<p>Raw HTML content</p>';
---
<Fragment set:html={htmlString} />
```

### Astro 和 JSX 间的差异

Astro 组件的语法是 HTML 的超集。它的设计使得任何有 HTML 或 JSX 经验的人都感到熟悉，但 `.astro` 文件和 JSX 之间有几个关键的区别。

#### 属性

在 Astro 中，所有 HTML 属性都使用标准的 `kebab-case` 格式，而不是 JSX 中使用的 `camelCase`。这甚至适用于 `class`，而 React 不支持。

```jsx del={1} ins={2} title="example.astro"
<div className="box" dataValue="3" />
<div class="box" data-value="3" />
```

#### 多元素

一个 Astro 组件模版可以渲染多个元素，无需像 JavaScript 或 JSX 那样将所有内容都包装在单个 `<div>` 或 `<>` 中。

```astro title="src/components/RootElements.astro"
---
// 包含多个元素的模板
---
<p>无需将元素包装在单个容器元素中。</p>
<p>Astro 支持模板中的多个根元素。</p>
```

#### 注释

在 Astro 中，可以使用标准的 HTML 注释或 JavaScript 风格的注释。

```astro title="example.astro"
---
---
<!-- HTML 注释语法在.astro 文件中是有效的 -->
{/* JS 注释语法也是有效的 */}
```

:::caution
HTML 风格的注释将包含在浏览器 DOM 中，而 JS 注释将被跳过。为了保留 TODO 消息或其他仅限于开发的解释，你可能希望使用 JavaScript 样式的注释。
:::
